package org.jeecg.config.mybatis;

import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.List;

/**
 * @author gbstart
 * @create 2024-07-13 11:29
 */
@ControllerAdvice
public class DataLogValueInterceptor implements RequestBodyAdvice {

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        AutoLog autoLog = methodParameter.getMethodAnnotation(AutoLog.class);
        return autoLog != null;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        return inputMessage;
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        Class<?> aClass = body.getClass();
           // 判断是否是实体
        String logtime= String.valueOf(System.nanoTime());
        try {
            if(isPropertyExist(aClass,"logtime")){
                Field logtimeField = aClass.getDeclaredField("logtime");
                logtimeField.setAccessible(true);
                logtimeField.set(body,logtime);
            }else {
                Class<?> superClass = aClass.getSuperclass();
                if(superClass != null && isPropertyExist(superClass,"logtime")){
                    Field parentlogtimeField = superClass.getDeclaredField("logtime");
                    parentlogtimeField.setAccessible(true);
                    parentlogtimeField.set(body,logtime);
                }
            }
        } catch (Exception e) {
//            e.printStackTrace();
        }
        this.setlogtime(body,logtime);
        return body;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }

    private void setlogtime(Object body,String logtime){
        Field[] declaredFields = body.getClass().getDeclaredFields();
        for (int i = 0; i < declaredFields.length; i++) {
            Field field = declaredFields[i];
            field.setAccessible(true);
            Class<?> type = field.getType();
            try {
                initlogtime(field,body,logtime);
            } catch (IllegalAccessException e) {

            }
        }
    }


    private void initlogtime(Field field,Object body,String logtime) throws IllegalAccessException {
        field.setAccessible(true);
        if (List.class.isAssignableFrom(field.getType())) {
            List myList = (List) field.get(body);
            if(!CollectionUtils.isEmpty(myList)){
                for (Object obj:myList) {
//                    obj.getClass().getd
                    Field[] fields = obj.getClass().getDeclaredFields();
                    for (int i = 0; i < fields.length; i++) {
                        initlogtime(fields[i],obj,logtime);
                    }
                }
            }
        }else {
            try {
                Class<?> aClass = body.getClass();
                Class<?> superClass = aClass.getSuperclass();
                if(isPropertyExist(aClass,"logtime")){
                    Field logtimeF = aClass.getDeclaredField("logtime");
                    logtimeF.setAccessible(true);
                    logtimeF.set(body,String.valueOf( System.nanoTime()));
                }else {
                    if(superClass != null && isPropertyExist(superClass,"logtime")){
                        Field parentlogtimeField = superClass.getDeclaredField("logtime");
                        parentlogtimeField.setAccessible(true);
                        parentlogtimeField.set(body,logtime);
                    }
                }
                if(isPropertyExist(aClass,"parentLogtime")){
                    Field parentLogtimeField = aClass.getDeclaredField("parentLogtime");
                    parentLogtimeField.setAccessible(true);
                    parentLogtimeField.set(body,logtime);
                }else {
                    if(superClass != null && isPropertyExist(superClass,"parentLogtime")){
                        Field plogtimeField = superClass.getDeclaredField("parentLogtime");
                        plogtimeField.setAccessible(true);
                        plogtimeField.set(body,logtime);
                    }
                }
            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }







    private boolean isPropertyExist(Class<?> aClass, String propertyName) {
        try {
            Field declaredField = aClass.getDeclaredField(propertyName);
            return true;
        } catch (NoSuchFieldException e) {
            return false;
        }
    }
}
